package com.polaris.live.ui.web

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.util.Base64
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.ValueCallback
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.lifecycle.lifecycleScope
import com.blankj.utilcode.util.ImageUtils
import com.blankj.utilcode.util.StringUtils
import com.bumptech.glide.Glide
import com.just.agentweb.AgentWeb
import com.just.agentweb.DefaultWebClient
import com.just.agentweb.IWebLayout
import com.polaris.live.R
import com.polaris.live.common.constant.ServerConfig
import com.polaris.live.common.mvvm.base2.BaseVbActivity
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.common.util.AndroidBug5497Workaround
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.SystemUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.databinding.ActivityWebBinding
import com.polaris.live.ui.web.js.JsBridgeProxy
import com.polaris.live.utils.CropUtils
import com.polaris.live.utils.WebUtils
import com.polaris.live.utils.route.RouterUtils
import com.polaris.live.utils.sensor.impl.WebModuleHelper
import kotlinx.coroutines.launch
import ren.yale.android.cachewebviewlib.WebViewCacheInterceptorInst
import java.io.File

/**
 * 网页显示页面
 *
 * @author Created by lucas on 2023/10/24 12:00
 * @since 1.0.0
 */
class WebActivity : BaseVbActivity<BaseViewModel, ActivityWebBinding>() {

    private var mAgentWeb: AgentWeb? = null

    private lateinit var mTitle: String
    private lateinit var mUrl: String

    private var mActCache: Boolean = false

    override fun initView(savedInstanceState: Bundle?) {
        mTitle = intent.getStringExtra("title") ?: ""

        val url = intent.getStringExtra("url") ?: ""
        mUrl = WebUtils.spliceUrlParams(WebUtils.formatUrl(url))

        if (WebUtils.isSafeUrl(url)) {
            resolveParameter()?.let {
                mUrl = StringBuilder(mUrl).apply {
                    it.forEach { (k, v) ->
                        append("&$k=$v")
                    }
                }.toString()
            }

            mActCache = url.substringAfter("#/").startsWith("actCache/")
        }

        initView()

        AndroidBug5497Workaround.assistActivity(this)
    }

    private fun resolveParameter(): Map<String, String>? {
        val parameter = intent.getStringExtra("parameter")
        return if (!parameter.isNullOrEmpty()) {
            JsonUtils.fromJson<Map<String, String>>(parameter)
        } else {
            null
        }
    }

    private fun initView() {
        if (mTitle.isNotEmpty()) {
            mBinding.title.text = mTitle
        }

        if (ServerConfig.isDebug()) {
            WebView.setWebContentsDebuggingEnabled(true)
        }

        val builder = AgentWeb.with(this)
            .setAgentWebParent(
                mBinding.llContent,
                LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
            )
            .useDefaultIndicator()
            .setWebChromeClient(mWebChromeClient)
            .setWebViewClient(object : com.just.agentweb.WebViewClient() {

                @Deprecated("deprecated")
                override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
                    if (SystemUtils.isSdkInt24()) {
                        return super.shouldOverrideUrlLoading(view, url)
                    }
                    return if (processUrl(view, url)) {
                        true
                    } else {
                        super.shouldOverrideUrlLoading(view, url)
                    }
                }

                override fun shouldOverrideUrlLoading(
                    view: WebView,
                    request: WebResourceRequest,
                ): Boolean {
                    val url = request.url.toString()

                    LogExt.logI("--net", url)

                    return if (processUrl(view, url)) {
                        true
                    } else {
                        super.shouldOverrideUrlLoading(view, request)
                    }
                }

                private fun processUrl(view: WebView, url: String): Boolean {
                    if (url.isNotEmpty() && url.startsWith(RouterUtils.Type.KEY_NATIVE)) {
                        if (url == RouterUtils.Type.KEY_ACTION + "finish") {
                            finish()
                            return true
                        }
                        RouterUtils.routerGoto(url)
                        return true
                    }

                    return false
                }

                override fun shouldInterceptRequest(
                    view: WebView,
                    request: WebResourceRequest,
                ): WebResourceResponse? {
                    return if (mActCache) {
                        val name = request.url?.pathSegments?.lastOrNull()
                        if (name != "index.html") {
                            WebViewCacheInterceptorInst.getInstance().interceptRequest(request)
                        } else {
                            super.shouldInterceptRequest(view, request)
                        }
                    } else {
                        super.shouldInterceptRequest(view, request)
                    }
                }

                override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {
                    return if (mActCache && !url.contains("index.html")) {
                        WebViewCacheInterceptorInst.getInstance().interceptRequest(url)
                    } else {
                        super.shouldInterceptRequest(view, url)
                    }
                }
            })
            .setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.ASK) //打开其他应用时，弹窗咨询用户是否前往其他应用
            .setMainFrameErrorView(R.layout.widget_item_error_full, -1)
            .setSecurityType(AgentWeb.SecurityType.STRICT_CHECK)
            .setWebLayout(WebLayout(this))
            .interceptUnkownUrl()

        mAgentWeb = builder.createAgentWeb()
            .ready()
            .go(mUrl)
            .apply {
                //注入对象,与js进行通信  js通过 window.android.方法名 调用我们客户端方法   android由我们自定义，方法参考JsBridgeProxy
                jsInterfaceHolder.addJavaObject(
                    "android",
                    JsBridgeProxy(this@WebActivity, this, mUrl)
                )

                if (ServerConfig.isDebug() || !ServerConfig.isProdServer()) {
                    WebModuleHelper.attach(this@WebActivity, this)
                }
            }

        initListener()
    }

    private fun initListener() {
        mBinding.ivBack.setOnClickListener {
            if (mAgentWeb?.back() == false) {
                finish()
            } else {
                if (mBinding.ivClose.visibility == View.GONE) {
                    mBinding.ivClose.visibility = View.VISIBLE
                }
            }
        }
        mBinding.ivClose.setOnClickListener {
            finish()
        }
    }

    fun addRightMenu(url: String, block: () -> Unit) {
        mBinding.ivRight.post {

        }
        lifecycleScope.launch {
            registerMenuView(mBinding.ivRight, url, block)
        }
    }

    fun addRightMenu2(url: String, block: () -> Unit) {
        lifecycleScope.launch {
            registerMenuView(mBinding.ivRight2, url, block)
        }
    }

    fun saveBase64Img(base64Url: String) {
        lifecycleScope.launch {
            val base64 = base64Url.substringAfter("base64,")
            // 解码 Base64 字符串
            val decodedBytes = Base64.decode(base64, Base64.DEFAULT)
            // 将字节数组转换为 Bitmap
            val bitmap = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.size)
            val save2Album = ImageUtils.save2Album(bitmap, Bitmap.CompressFormat.PNG)
            if (save2Album != null) {
                ToastGravity.showGravity(StringUtils.getString(com.polaris.live.translation.R.string.save_success))
            }
        }
    }

    fun upDataUserInfo(block: () -> Unit) {
        lifecycleScope.launch {
            try {
                block.invoke()
            } catch (_: Throwable) {
            }
        }
    }

    private fun registerMenuView(menuView: ImageView, url: String, block: () -> Unit) {
        if (isDestroyed) {
            return
        }

        menuView.visibility = View.VISIBLE

        Glide.with(this)
            .load(url)
            .into(menuView)

        menuView.setOnClickListener {
            try {
                block()
            } catch (_: Throwable) {
            }
        }
    }

    private val mWebChromeClient = object : com.just.agentweb.WebChromeClient() {
        override fun onReceivedTitle(view: WebView, title: String) {
            super.onReceivedTitle(view, title)
            if (mTitle.isEmpty()) {
                mBinding.title.text = title
            }
        }

        override fun onShowFileChooser(
            webView: WebView?,
            filePathCallback: ValueCallback<Array<Uri>>?,
            fileChooserParams: FileChooserParams?,
        ): Boolean {
            if (fileChooserParams == null || filePathCallback == null) return false
            val intent = fileChooserParams.createIntent()
            val mimeTypes = intent?.extras?.getStringArray(Intent.EXTRA_MIME_TYPES)
            // 检查 MIME 类型
            mimeTypes?.let {
                val type = it.getOrNull(0) ?: return true
                if (type.contains("image/*")) {
                    CropUtils.startAlbum(this@WebActivity, { photoUrl ->
                        // 确保 photoUrl 不为空，并且解析后的 Uri 有效
                        if (!photoUrl.isNullOrEmpty()) {
                            val uri = Uri.fromFile(File(photoUrl))
                            filePathCallback.onReceiveValue(arrayOf(uri))
                        } else {
                            filePathCallback.onReceiveValue(null)
                        }
                    }, {
                        // 处理拍照失败或其他异常
                        filePathCallback.onReceiveValue(null)
                    })
                    return true
                } else if (type.contains("video/*")) {
                    CropUtils.startVideo(this@WebActivity, { photoUrl ->
                        // 确保 photoUrl 不为空，并且解析后的 Uri 有效
                        if (!photoUrl.isNullOrEmpty()) {
                            val uri = Uri.fromFile(File(photoUrl))
                            filePathCallback.onReceiveValue(arrayOf(uri))
                        } else {
                            filePathCallback.onReceiveValue(null)
                        }
                    }, {
                        // 处理拍照失败或其他异常
                        filePathCallback.onReceiveValue(null)
                    })
                    return true
                }
            }
            // 如果 MIME 类型不匹配，通知 WebView 操作已取消
            filePathCallback.onReceiveValue(null)
            return true
        }
    }

    class WebLayout(context: Context) : IWebLayout<WebView, ViewGroup> {

        private var mContentLayout: FrameLayout
        private var mWebView: WebView

        init {
            mContentLayout =
                LayoutInflater.from(context).inflate(R.layout.widget_web, null) as FrameLayout
            mWebView = mContentLayout.findViewById(R.id.web_view)
        }

        override fun getLayout(): ViewGroup {
            return mContentLayout
        }

        override fun getWebView(): WebView {
            return mWebView
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        return mAgentWeb?.handleKeyEvent(keyCode, event) == true || super.onKeyDown(keyCode, event)
    }

    override fun onPause() {
        mAgentWeb?.webLifeCycle?.onPause()
        super.onPause()
    }

    override fun onStop() {
        mAgentWeb?.webCreator?.webView?.loadUrl(String.format("javascript:%s(%s)", "onHide", ""))
        super.onStop()
    }

    override fun onResume() {
        mAgentWeb?.webCreator?.webView?.loadUrl(String.format("javascript:%s(%s)", "onShow", ""))
        mAgentWeb?.webLifeCycle?.onResume()
        super.onResume()
    }

    override fun onDestroy() {
        super.onDestroy()

        mAgentWeb?.webLifeCycle?.onDestroy()
    }
}